const shortId = () => {
  return 'omapedal';
};

 const makeCommandId = (commandId) => {
  console.log("makeCommandId:"+commandId);
  return `extension-${shortId()}-${commandId}`;
};

 const registerCommand = (id, callback = () => {}) => {
  return api('createCommand', {
    [makeCommandId(id)]: callback
  });
};

 const navigateToPage = (url) => {
  window.open(url, '_blank');
};

 const doCommand = (command, args = []) => {
  return api('doCommand', {
    cmd: command,
    args: args
  });
};

 const getSource = () => {
  return api('getSource', {
    type: 'json'
  });
};

 const getActiveTabInfo = () => {
  return callByEditor({
    func: 'getActiveTabInfo',
    args: []
  });
};

 const getGVars = () => {
  return callByEditor({
    func: "getGvars",
    args: []
  });
};

const getBOMFromPCBEditor = () => {
  return api('editorCall', {
    cmd: 'getBOMFromPCBEditor',
    args: []
  });
};


registerCommand('layout', () => {
  console.log('registerCommand layout run');
});


api('createToolbarButton', {    
    fordoctype: 'pcb',
    menu: [
      {
        text: 'Layout',
        cmd: makeCommandId('layout')
      }
    ]
});



class Component{
    constructor(name, width, height, x, y, connections){
        this.name = name;
        this.width = width;
        this.height = height;
        this.connections = [];
        this.connections = this.connections.length == 0 ? [] : connections;
        this.x = x;
        this.y = y;
        this.locked = false; //元器件是否锁定坐标
    }

    add_connection(component){
        this.connections.push(component);
    }
}





class PCBPlacer{
    constructor(width, height){
        this.pcb_width = width;
        this.pcb_height = height;
        this.components = [];
        this.attraction_coeff = 0.01;   //吸引力系数
        this.repulsion_coeff = 10000;    //斥力系数
        this.edge_repulsion = 100;       //边缘斥力系数
        this.damping = 0.85;             //阻尼系数
        this.max_speed = 2.0;            //最大移动速度
    }

        
    add_component(component){
        this.components.push(component);
    }
        
    calculate_forces(){
        var forces = new Array(this.components.length).fill(0).map(() => new Array(2).fill(0));
        
        for(var ic = 0; ic < this.components.length; ic++){
            for(var io = 0; io < this.components[ic].connections.length; io++){

                var j_idx = -1;
                for(var j = 0;j < this.components.length; j++){
                    if(this.components[ic].connections[io].name == this.components[j].name){
                        j_idx = j;
                        break;
                    }
                }

                dx = this.components[j_idx].x - this.components[ic].x;
                dy = this.components[j_idx].y - this.components[ic].y;
                distance = Math.hypot(dx, dy); //计算dx，dy为直角边的三角形的斜边长度

                if(distance > 0){
                    force = this.attraction_coeff * distance;
                    forces[ic][0] += force * dx / distance;
                    forces[ic][1] += force * dy / distance;
                }
            }
        }

        for(var i = 0; i < this.components.length; i++){
            for(var j = i + 1; j < this.components.length; j++){
                var comp1 = this.components[i];
                var comp2 = this.components[j];
                
                var dx = comp2.x - comp1.x;
                var dy = comp2.y - comp1.y;
                var distance = Math.hypot(dx, dy);

                var min_distance = (comp1.width + comp2.width)/2 + 5;
                if(distance < min_distance){
                    force = this.repulsion_coeff / Math.max(distance, 0.1) * Math.max(distance, 0.1);
                    forces[i][0] -= force * dx / distance;
                    forces[i][1] -= force * dy / distance;
                    forces[j][0] += force * dx / distance;
                    forces[j][1] += force * dy / distance;
                }
            }
        }


        for(var i = 0; i < this.components.length; i++){
            var comp = this.components[i];
            //左边界
            var force = this.edge_repulsion / (comp.x + 1);
            forces[i][0] += force;
            // 右边界
            force = this.edge_repulsion / (this.pcb_width - comp.x + 1);
            forces[i][0] -= force;
            // 下边界
            force = this.edge_repulsion / (comp.y + 1);
            forces[i][1] += force;
            // 上边界
            force = this.edge_repulsion / (this.pcb_height - comp.y + 1);
            forces[i][1] -= force;
        }

        return forces;
    }
    
    

    update_positions(forces){
        for (var i = 0; i < this.components.length; i++) {
            if (this.components[i].locked == true){
                continue;
            }

            //限制最大速度
            var fx = Math.max(Math.min(forces[i][0], this.max_speed), -this.max_speed);
            var fy = Math.max(Math.min(forces[i][1], this.max_speed), -this.max_speed);
            
            this.components[i].x += fx * this.damping;
            this.components[i].y += fy * this.damping;
            
            // 保持元件在PCB边界内
            this.components[i].x = Math.max(this.components[i].width/2, Math.min(this.pcb_width - this.components[i].width/2, this.components[i].x));
            this.components[i].y = Math.max(this.components[i].height/2, Math.min(this.pcb_height - this.components[i].height/2, this.components[i].y));
        }    
    }




    // visualize(){
        
    //     var canvas = document.getElementById('canvas');
    //     var ctx = canvas.getContext("2d");
    //     var rect = canvas.getBoundingClientRect();
    //     var w = rect.width;
    //     var h = rect.height;
    //     ctx.clearRect(0,0, w, h);
        
    //     // 绘制元件
    //     for (var i = 0; i < this.components.length; i++) {
    //         var comp = this.components[i];
    //         ctx.fillRect(comp.x+comp.width/2, comp.y+comp.height/2, comp.width, comp.height);


        
    //         // for(var j =0; j < comp.connections.length; j++){
    //         //     var co = comp.connections[j];
    //         //     ctx.moveTo(comp.x, comp.y);
    //         //     ctx.lineTo(co.x, co.y);
    //         //     ctx.stroke();
    //         // }
    //     }
    // }   
}



function layout(){
  console.log('layout run');
  var ids = api('getSelectedIds');
  var ids_arr = [];
  if(ids != ''){
    ids_arr = ids.split(",");
  }
  console.log(ids_arr);

  //start处理选中的元器件
  var cps = [];
  for(var i = 0; i < ids_arr.length; i++){
    var sel = $($('iframe').contents()[0]).find('rect[attach_libid="'+ ids_arr[i] +'"]')[0];
    var w = $(sel).attr('width');
    var h = $(sel).attr('height');
    var x = $(sel).attr('x');
    var y = $(sel).attr('y');
    var obj = api('getShape', {id:ids_arr[i]});
    var c = new Component(ids_arr[i], w, h, x, y, []);
    if(obj['head']['locked'] == '1'){
        c.locked = true;
    } else {
        c.locked = false;
    }

    cps.push(c);
  }
  console.log(cps);
  //end处理选中的元器件



  //start获取文档层布局区域
  var layput_rear = $($('iframe').contents()[0]).find('rect[layerid=12]')[0];
  var layout_w = $(layput_rear).attr('width');
  var layout_h = $(layput_rear).attr('hight');
  var layout_x = $(layput_rear).attr('x');
  var layout_y = $(layput_rear).attr('y');
  //end获取文档层布局区域


  //start处理元器件导线链接关系

  
}

$(`div[cmd="${makeCommandId(`layout`)}"]`).click(e => layout());